package com.apes.fn.scm.used.server;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.used.model.Used;
import com.apes.fn.scm.used.model.UsedStock;
import com.apes.fn.scm.used.model.UsedStore;
import com.apes.fn.scm.used.model.UsedStoreItem;
import com.apes.fn.scm.used.repository.UsedRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.repository.CustomRepository;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.fn.scm.used.repository.UsedStoreRepository;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.product.model.Classify;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.stock.transfer.model.Pick;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/***
 * 旧件入库
 */
@Service("usedStoreService")
public class UsedStoreService extends DomainService {
    @Autowired
    UsedStoreRepository usedStoreRepository;
    @Autowired
    UsedStockService usedStockService;
    @Autowired
    UsedRepository usedRepository;
    @Autowired
    BusinessAttributeValueRepository businessAttributeValueRepository;
    @Autowired
    LocationRepository locationRepository;
    /***
     * 创建
     */
    public UsedStore create(SimpleRequest request) {
        UsedStore usedStore = request.getO(UsedStore.class);
        usedStore.setState("create");
        checkItemData(usedStore);
        return usedStoreRepository.saveAndFlush(usedStore);
    }

    /***
     * 修改
     */
    public UsedStore update(SimpleRequest request) {
        isValid(request, usedStoreRepository);
        UsedStore usedStore = request.getO(UsedStore.class);
        if (usedStore.getStoreType().getId().contains("normal")) checkMX(usedStore);
        checkItemData(usedStore);
        return usedStoreRepository.saveAndFlush(usedStore);
    }


    /***
     * 删除
     */
    public String delete(SimpleRequest request) {
        isValid(request, usedStoreRepository);
        UsedStore usedStore = request.getO(UsedStore.class);
        usedStore.setState("delete");
        usedStore.setDeleteId(request.getPerson());
        usedStore.setDeleteDate(new Date());
        usedStoreRepository.delete(usedStore);
        return "删除成功！";
    }

    /***
     * 验收
     */
    public UsedStore check(SimpleRequest request) {
        isValid(request, usedStoreRepository);
        UsedStore usedStore = request.getO(UsedStore.class);
        //验证明细数据
        checkItemData(usedStore);
        if (usedStore.getStoreType().getId().contains("normal")) checkMX(usedStore);

        usedStore.setState("done");
        boolean flag = usedStore.getUsedStoreItems().stream().anyMatch(usedStoreItem -> usedStoreItem.getUsed() == null || usedStoreItem.getStoreMethod() == null);
        if (flag) throw new RuntimeException("验收时入库方式和旧件不能为空");
        usedStore.setCheckId(request.getPerson());
        usedStore.setCheckDate(new Date());

        for (UsedStoreItem usedStoreItem : usedStore.getUsedStoreItems()) {
            // 自提旧件过滤
            if (usedStoreItem.getStoreMethod().getId().equals("UsedStoreItem.storeMethod.pickUp")) {
                continue;
            }
            // 写旧件库存(正常库存/保险库存)
            usedStockService.setUsedStock(
                    usedStoreItem.getUsed(),
                    usedStore.getLocation(),
                    usedStoreItem.getQtyStore(),
                    usedStoreItem.getCompany(),
                    usedStoreItem.getStoreMethod().getId().equals("UsedStoreItem.storeMethod.normal")
            );


        }

        return usedStoreRepository.saveAndFlush(usedStore);
    }

    public void checkMX(UsedStore oldUsedStore) {
        List<UsedStoreItem> oldUsedStoreItems = oldUsedStore.getUsedStoreItems();
        if (oldUsedStoreItems.stream().anyMatch(usedStoreItem -> usedStoreItem.getId()==null)) new RuntimeException("正常入库不允许添加或删除明细");
        UsedStore usedStore = usedStoreRepository.findOne(oldUsedStore.getId());
        usedStore.getUsedStoreItems().forEach(usedStoreItem -> {
            List<UsedStoreItem> items = oldUsedStoreItems.stream().filter(item -> usedStoreItem.getId().equals(item.getId())).collect(Collectors.toList());
            if (items.size() == 0) throw new RuntimeException("正常入库不允许添加或删除明细");
        });
    }

    /***
     * 验证明细数据
     */
    private void checkItemData(UsedStore usedStore) {
        usedStore.getUsedStoreItems().stream().forEach(item -> {
            //旧件存在时，入库数量不能小于等于0
            if(item.getUsed() != null && item.getQtyStore() <= 0 ) throw new RuntimeException("存在入库数量小于等于零的旧件,旧件编码：" + item.getUsed().getId());
            //入库模式为盘盈入库时，只能选择正常入库方式
            if ("UsedStore.storeType.inventoryProfit".equals(usedStore.getStoreType().getId()) && !"UsedStoreItem.storeMethod.normal".equals(item.getStoreMethod().getId())) throw new RuntimeException("明细的入库方式请选择：正常!");
            //明细的商品和旧件不能同时为空
            if (item.getProduct() == null && item.getUsed() == null) throw new RuntimeException("明细的商品和旧件不能同时为空！");
            //验收时必须存在旧件
//            if ("create".equals(usedStore.getState()) && item.getUsed() == null) throw new RuntimeException("旧件不能为空！");
        });
    }

    /***
     * 数据是否合法
     * @param request
     * @param repository
     */
    private Model isValid(SimpleRequest request, CustomRepository repository) {
        Model oldModel = (Model) repository.findOne((String) request.get("id"));
        if (oldModel == null) throw new RuntimeException("订单【" + request.get("id") + "】在系统中不存在。");
        if (oldModel.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        return oldModel;
    }


    /**
     * 功能：服务方案审核新增旧件入库单
     * 1. 通过品类去匹配旧件
     * 2. 存在一条自动写入，存在多条让其手选
     *
     * 1. 统一服务
     * 2. 非内协
     * 3. 非外协
     * 4. 领用数量大于零
     * 5. 品类一致
     * @param request
     * @return
     */
    @Listener(topic = "event:fn.service.usedStore")
    public void qualityTest(SimpleRequest request) {
        ServicePlan servicePlan = request.getO(ServicePlan.class);

        List<UsedStoreItem> usedStoreItems = servicePlan.getServicePlanItems().stream()
                .filter(
                        servicePlanItem -> servicePlanItem.isServiceState() &&
                        servicePlanItem.getAssistType().getId().equals("ServicePlanItem.assistType.normal") &&
                        servicePlanItem.getQtyReceive() > 0
                ).map(servicePlanItem -> {
                    UsedStoreItem usedStoreItem = new UsedStoreItem();
                    Classify classify = servicePlanItem.getProduct().getClassify();
                    List<Used> usedList = usedRepository.findAll(
                            JpaDsl.toCriteriaByEq(
                                    "usedClassifyItems.classify", classify
                            )
                    );

                    if( usedList.size() == 0 ) return null;
                    if( usedList.size() == 1 ) usedStoreItem.setUsed(usedList.get(0));
                    usedStoreItem.setProduct(servicePlanItem.getProduct());
                    usedStoreItem.setQtyStore(servicePlanItem.getQtyReceive());
                    usedStoreItem.setSourceUom(servicePlanItem.getUom());

                    usedStoreItem.setStoreMethod(businessAttributeValueRepository.findOne("UsedStoreItem.storeMethod.normal"));
                    usedStoreItem.setOriginLine(servicePlanItem.getId());
                    usedStoreItem.setProduct(servicePlanItem.getProduct());

                    return usedStoreItem;
                }).filter(usedStoreItem -> usedStoreItem != null).collect(Collectors.toList());

        if( usedStoreItems.size() == 0 ) return;

        UsedStore usedStore = new UsedStore();

        usedStore.setSource(servicePlan.getId());
        usedStore.setSourceBusinessType(servicePlan.getInnerBusinessType());
        usedStore.setSourceBusinessTypeName("服务方案");

        usedStore.setCompany(servicePlan.getCompany());

        usedStore.setLocation(locationRepository.findOne(
                JpaDsl.toCriteriaByEq(
                        "dept", servicePlan.getBelongDept(),
                        "usage.id", "1"
                )
        ).orElse(null));

        usedStore.setDept(servicePlan.getBelongDept());

        // 设置保险入库标记
        usedStore.setInsuranceRecoverySign( servicePlan.getSourceBusinessType() != null && servicePlan.getSourceBusinessType().equals("LossQuotation"));

        usedStore.setState("create");

        usedStore.setUsedStoreItems(usedStoreItems);

        usedStoreRepository.saveAndFlush(usedStore);
    }


    public Page<Used> find(SimpleRequest request) {
        List<JSONObject> filters = request.get("condition");
        JSONObject classify = (JSONObject)((JSONObject)((JSONObject)request.getJO().get("conditionModel")).get("node")).get("classify");
        for (JSONObject filter : filters) {
            if (filter.getString("field").equals("valid") && filter.getString("value").equals("1")) {
                filter.put("value", true);
            }
        }
        Page<Used> useds = usedRepository.findAll(JpaDsl.toCriteria(filters),PageRequest.of(request.get("page"), request.get("size")));
        if (classify == null) return useds;
        String id = classify.getString("id");
        Page<Used> usedList = usedRepository.find(id,PageRequest.of(request.get("page"),request.get("size")));
        if (id != null) return usedList;
        return null;
    }



    public Page<UsedStore> findAllUserStore(SimpleRequest request) {
        Group group = findAllCore(request);
        return usedStoreRepository.findAll(group.build(true), JpaDsl.getPageable(request));
    }
    /***
     * 抽取的公共逻辑
     */
    private Group findAllCore(SimpleRequest request) {
        Group group = JpaDsl.getGroup(request);

        List<Filter> filters = group.getFilters();
        // 找到需要重构的条件
        Filter filter = filters.stream().filter( item -> item.getField().equals("id")).findFirst().orElse(null);
        // 重构条件
        if( filter != null ) {
            filters.remove(filter); // 移除当前选项
            group.addGroup(createIdGroup(filter));
        }
        return group;
    }


    /***
     * 构建 Group
     */
    private Group createIdGroup(Filter filter) {
        Group idGroup = new Group();
        idGroup.setOperator("or");
        idGroup.addFilters(
                JpaDsl.toFilter(
                        "id","EQ", filter.getValue(),
                        "source", "EQ", filter.getValue()
                )
        );
        return idGroup;
    }
}
